// http.ts
import router from '@/router';
import { useUserStore } from '@/stores/user';
import { API_ROOT } from '@/types/constant';
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import Axios, { AxiosError } from 'axios';
import { ElMessage } from 'element-plus';
import Cookies from 'js-cookie';
type Method = 'get' | 'delete' | 'post' | 'put';

type RequestConfig = AxiosRequestConfig & {
  disableErrorToast?: boolean;
  skipInterceptor?: boolean;
};
type MethodFn = <D = any>(url: string, payload?: any, config?: RequestConfig) => Promise<D>;
type RequestFn = <D = any>(
  params: Omit<AxiosRequestConfig, 'method'> & { method: Method; payload?: any; config?: RequestConfig },
) => Promise<D>;
type LLPPAxiosResponse<T = any, D = any> = Omit<AxiosResponse<T, D>, 'config'> & { config: RequestConfig };
class HttpClient {
  private axios: AxiosInstance;

  constructor() {
    this.axios = Axios.create({ timeout: 80000, withCredentials: true });

    this.axios.interceptors.request.use(
      (config) => {
        config.headers['Content-Type'] = 'application/json;charset=utf-8';
        const user = Cookies.get('web-token');
        config.headers['token'] = user; // 设置请求头
        return config;
      },
      (error) => {
        console.error('request error: ' + error); // for debug
        return Promise.reject(error);
      },
    );

    this.axios.interceptors.response.use(
      (res: LLPPAxiosResponse<any>) => {
        const resp = res.data;
        // if (resp.code === '401') {
        //   const userStore = useUserStore();
        //   userStore.logout();
        //   router.push('/login');
        //   return Promise.reject(resp);
        // }
        return res.data;
      },
      (err: AxiosError<any>) => {
        ElMessage.error(err.message);
        return Promise.reject(err);
      },
    );
  }

  request: RequestFn = ({ method, url, payload, config }) => {
    const reqConfig: AxiosRequestConfig = { method, url: `${API_ROOT}${url}`, ...config };
    if (['get', 'delete'].includes(method)) {
      reqConfig.params = payload;
    } else {
      reqConfig.data = payload;
    }
    return this.axios.request(reqConfig);
  };

  public get: MethodFn = (url, payload, config) => this.request({ method: 'get', url, payload, config });
  public delete: MethodFn = (url, payload, config) => this.request({ method: 'delete', url, payload, config });
  public put: MethodFn = (url, payload, config) => this.request({ method: 'put', url, payload, config });
  public post: MethodFn = (url, payload, config) => this.request({ method: 'post', url, payload, config });

  public upload: MethodFn = (url, payload, config) =>
    this.request({
      method: 'put',
      url,
      payload,
      config: { headers: { 'Content-Type': 'multipart/form-data' }, ...config },
    });

  public download: MethodFn = (url, payload, config) =>
    this.request({ method: 'get', url, payload, config: { responseType: 'blob', skipInterceptor: true, ...config } });
}

export const http = new HttpClient();
